#pragma once
#include "core/ComponentInterface.h"


//interface
class IComponent
{
public:
	virtual IComponentInterface* getInterface()=0;

	
};

////////////////////////////////////////////////////////////////
class Entity;

template <typename INTERFACE>
class BaseComponent : public INTERFACE, public IComponent
{	
	Entity* const _owner;
	
public:
	inline BaseComponent(Entity* const owner) : _owner(owner) {};
	inline BaseComponent(void) : _owner(NULL) {};

	virtual inline ~BaseComponent(void) {};


	inline INTERFACE* getInterface()
	{
		return this;
	}

	inline Entity* getOwner() const
	{
		return _owner;
	}

	
};


///////////////////////////////////////////////////////////////////////////////////


class ENGINE_API ComponentContainer
{
	std::map<unsigned, IComponent*> components;


public:
	ComponentContainer();
	virtual ~ComponentContainer();


	
	void addComponent(IComponent* component);
	void removeComponent(IComponent* component);
	
	template<typename T>
	inline T* findInterface()
	{
		return findInterfaceByID<T>( T::InterfaceID() );
	}

private:
	template<typename T> 
	inline T* findInterfaceByID( unsigned interfaceId )
	{
		IComponentInterface* ret = NULL;
		
		std::map <unsigned, IComponent*> :: const_iterator it;
		it = components.find(interfaceId);
		if (it!=components.end())
		{
			IComponent* c = it->second;
			if (c!=NULL)
				ret = c->getInterface();
		}

		return static_cast<T*>(ret);
	}


	
};

////////////////////////////////////////////////////////////////////////

//TODO cambiare
typedef IComponent Component;

//! Defines the identifier used to keep track of components
typedef unsigned int ComponentTypeId;

//! Defines a string-based identifier for a GameComponent type
typedef std::string ComponentTypeName;

typedef std::map<ComponentTypeId, Component *> ComponentByTypeIdLkup;



class ENGINE_API ComponentContainer2
{
public:

	ComponentContainer2(void);
	
	~ComponentContainer2(void);


	//! Registers the Component
	template <class T>
	void registerComponent(T *component) 
	{ 
		ComponentTypeId typeId = mComponentTypes->getComponentIdFromType<T>();
		registerComponentUnsafely(component, typeId);
	}

	
	//! Get the Component, or null if there is no matching Component attached.
	template <class T>
	T *getComponent() 
	{
		ComponentTypeId typeId = mComponentTypes->getComponentIdFromType<T>();
		return (T*) getComponentUnsafely(typeId); 
	}
	
	//! Remove the Component, and by default delete it

	/// Optionally, you may pass false for deleteComponent, but you will now have to delete the
	/// Component yourself (unless you register it to another object). Generally, you
	/// should never do this except to move a Component from one object to another.
	void unregisterComponent(Component         *component,
								bool deleteComponent = true);

	ComponentByTypeIdLkup::iterator begin() { return mStringComponentMap.begin(); }
	ComponentByTypeIdLkup::iterator end() { return mStringComponentMap.end(); }

	size_t  count() { return mStringComponentMap.size(); }


 protected:

	//! Allows registration using an arbitrary string value
	void registerComponentUnsafely(
		Component         *component, 
		ComponentTypeId    typeName);

	//! Allows getting a component by arbitrary string value
	Component *getComponentUnsafely(ComponentTypeId typeId);

	//! Allows unregistering a component by arbitrary string value
	void unregisterComponentUnsafely(
		Component         *component,
		ComponentTypeId    typeName);


private:
	//IGameObjectEnv& mGameObjectEnv;
	ComponentByTypeIdLkup mStringComponentMap;

	//cached reference to ObjectManager's ComponentTypeRegistry
	//ComponentTypeRegistry *mComponentTypes;


};